using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Net;
using System.Web.UI;
using System.Configuration; 

namespace GoogleGeocoder
{
    public interface ISpatialCoordinate
    {
        decimal Latitude {get; set; } 
        decimal Longitude {get; set; } 
    }

    /// <summary>
    /// Coordiate structure. Holds Latitude and Longitude.
    /// </summary>
    public struct Coordinate : ISpatialCoordinate
    {
        private decimal _latitude; 
        private decimal _longitude;

        public Coordinate(decimal latitude, decimal longitude)
        {
            _latitude = latitude;
            _longitude = longitude; 
        }

        #region ISpatialCoordinate Members

        public decimal  Latitude
        {
	        get 
	        { 
		        return _latitude; 
	        }
	        set 
	        { 
		        this._latitude = value; 
	        }
        }

        public decimal  Longitude
        {
	        get 
	        { 
		        return _longitude; 
	        }
	        set 
	        { 
		        this._longitude = value;
	        }
        }

        #endregion
    }
    
    public class Geocode
    {
        private const string _googleUri = "http://maps.google.com/maps/geo?q=";
        private const string _outputType = "csv"; // Available options: csv, xml, kml, json

        /// <summary>
        /// Returns a Uri of the Google code Geocoding Uri.
        /// </summary>
        /// <param name="address">The address to get the geocode for.</param>
        /// <returns>A new Uri</returns>
        private static Uri GetGeocodeUri(string address)
        {
            string googleKey = ConfigurationManager.AppSettings["googleApiKey"].ToString(); 
            address = HttpUtility.UrlEncode(address);
            return new Uri(String.Format("{0}{1}&output={2}&key={3}", _googleUri, address, _outputType, googleKey));
        }

        /// <summary>
        /// Gets a Coordinate from a address.
        /// </summary>
        /// <param name="address">An address.
        ///     <remarks>
        ///         <example>
        ///         3276 Westchester Ave, Bronx, NY 10461
        /// 
        ///         or 
        /// 
        ///         New York, NY 
        /// 
        ///         or
        /// 
        ///         10461  (just a zipcode)
        ///         </example>
        ///     </remarks>
        /// </param>
        /// <returns>A spatial coordinate that contains the latitude and longitude of the address.</returns>
        public static Coordinate GetCoordinates(string address)
        {
            WebClient client = new WebClient();
            Uri uri = GetGeocodeUri(address);
            
            /*  The first number is the status code, 
             * the second is the accuracy, 
             * the third is the latitude, 
             * the fourth one is the longitude.
             */
            string[] geocodeInfo = client.DownloadString(uri).Split(',');

            return new Coordinate(Convert.ToDecimal(geocodeInfo[2]), Convert.ToDecimal(geocodeInfo[3]));
        }
        
    }
}
